package org.tgit.gateway.filter;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.pattern.PathPattern.PathMatchInfo;


/**
 * 
 * @ClassName: PreGatewayFilterFactory
 * @Description: TODO(自定义前置过滤器)
 * @author fanzaijun
 * @date 2018年8月8日 下午6:04:22
 *
 */
@Component
public class PreErrorGatewayFilterFactory extends AbstractGatewayFilterFactory<PreErrorGatewayFilterFactory.Config> {

	public static final String TEMPLATE_KEY = "template";

	public PreErrorGatewayFilterFactory() {
		super(Config.class);
	}

	@Override
	public List<String> shortcutFieldOrder() {
		return Arrays.asList(TEMPLATE_KEY);
	}

	@Override
	public GatewayFilter apply(Config config) {
		UriTemplate uriTemplate = new UriTemplate(config.template);
		return (exchange, chain) -> {
			Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
			URI routeUri = route.getUri();
			String scheme = routeUri.getScheme();
			if (isAlreadyRouted(exchange) && !"forward".equals(scheme)) {
				PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
				ServerHttpRequest req = exchange.getRequest();
				addOriginalRequestUrl(exchange, req.getURI());
				Map<String, String> uriVariables;

				if (variables != null) {
					uriVariables = variables.getUriVariables();
				} else {
					uriVariables = Collections.emptyMap();
				}

				URI uri = uriTemplate.expand(uriVariables);
				String newPath = uri.getRawPath();

				exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);

				ServerHttpRequest request = req.mutate()
						.path(newPath)
						.build();

				return chain.filter(exchange.mutate().request(request).build());
			}
			return chain.filter(exchange);
		
		};
	}

	public static class Config {
		private String template;

		public String getTemplate() {
			return template;
		}

		public void setTemplate(String template) {
			this.template = template;
		}
	}
}

